nexus\api\event/arc.rs
1//! [ArcDPS EVTC](https://deltaconnected.com/arcdps/) bridge events.
2
3use super::Event;
4use evtc::agent::realtime::Agent;
5use std::ffi::{CStr, c_char};
6
7pub use evtc;
8
9/// ArcDPS EVTC combat local event.
10pub const COMBAT_LOCAL: Event<CombatData> =
11 unsafe { Event::new("EV_ARCDPS_COMBATEVENT_LOCAL_RAW") };
12
13/// ArcDPS EVTC combat squad event.
14pub const COMBAT_SQUAD: Event<CombatData> =
15 unsafe { Event::new("EV_ARCDPS_COMBATEVENT_SQUAD_RAW") };
16
17/// ArcDPS self join event.
18///
19/// Payload is [`AgentUpdate`] of the self player agent.
20///
21/// Events of this type are triggered upon map load.
22/// The last event can be retriggered on demand by addons sending an [`REPLAY_SELF_JOIN`] event.
23pub const SELF_JOIN: Event<AgentUpdate> = unsafe { Event::new("EV_ARCDPS_SELF_JOIN") };
24
25/// Replays the last [`SELF_JOIN`] event.
26pub const REPLAY_SELF_JOIN: Event<()> = unsafe { Event::new("EV_REPLAY_ARCDPS_SELF_JOIN") };
27
28/// ArcDPS self leave event.
29///
30/// Payload is [`AgentUpdate`] of the self player agent.
31///
32/// Events of this type are triggered when changing instance or leaving a party / squad.
33pub const SELF_LEAVE: Event<AgentUpdate> = unsafe { Event::new("EV_ARCDPS_SELF_LEAVE") };
34
35/// ArcDPS squad join event.
36///
37/// Payload is [`AgentUpdate`] of an allied player agent.
38/// Events of this type are triggered when allied players in your instance join your party/squad or when allied players in your party/squad join your instance.
39/// These events have a 2 second delay.
40///
41/// Nexus tracks all players in your squad and can retrigger these events on demand by addons sending an [`REPLAY_SQUAD_JOIN`] event.
42/// This is intended to be used during addon load, you should be careful to handle duplicates since this can be triggered by other addons.
43pub const SQUAD_JOIN: Event<AgentUpdate> = unsafe { Event::new("EV_ARCDPS_SQUAD_JOIN") };
44
45/// Replays [`SQUAD_JOIN`] events for the current squad.
46pub const REPLAY_SQUAD_JOIN: Event<()> = unsafe { Event::new("EV_REPLAY_ARCDPS_SQUAD_JOIN") };
47
48/// ArcDPS squad leave event.
49///
50/// Payload is [`AgentUpdate`] of an allied player agent.
51///
52/// Events of this type are triggered when allied players in your instance and party/squad either leave your instance or leave your party/squad.
53/// You will not recieve these events if you are the one to change instance or leave the party/squad.
54/// These events have a 2 second delay.
55pub const SQUAD_LEAVE: Event<AgentUpdate> = unsafe { Event::new("EV_ARCDPS_SQUAD_LEAVE") };
56
57/// ArcDPS target changed event.
58///
59/// Events of this type are triggered when you target an agent.
60/// The last event can be retriggered on demand by addons sending an [`REPLAY_TARGET_CHANGED`] event.
61pub const TARGET_CHANGED: Event<AgentUpdate> = unsafe { Event::new("EV_ARCDPS_TARGET_CHANGED") };
62
63/// Replays the [`TARGET_CHANGED`] event for the current target.
64pub const REPLAY_TARGET_CHANGED: Event<()> =
65 unsafe { Event::new("EV_REPLAY_ARCDPS_TARGET_CHANGED") };
66
67/// ArcDPS player account name.
68///
69/// Triggered on first map load.
70/// Can be triggered on demand by sending `"EV_REQUEST_ACCOUNT_NAME"`.
71pub const ACCOUNT_NAME: Event<c_char> = unsafe { Event::new("EV_ACCOUNT_NAME") };
72
73/// ArcDPS agent update.
74#[derive(Debug, Clone)]
75#[repr(C)]
76pub struct AgentUpdate {
77 /// Account name.
78 account: [c_char; 64],
79
80 /// Character name.
81 character: [c_char; 64],
82
83 /// ArcDPS id of the agent.
84 pub id: usize,
85
86 /// Instance id of the agent.
87 pub instance_id: usize,
88
89 /// Whether the agent has been added or removed.
90 added: u32,
91
92 /// Whether the agent is the new target.
93 target: u32,
94
95 /// Whether the agent is self.
96 is_self: u32,
97
98 /// Agent profession.
99 pub prof: u32,
100
101 /// Agent elite specialization.
102 pub elite: u32,
103
104 /// Agent team.
105 pub team: u16,
106
107 /// Agent subgroup.
108 pub subgroup: u16,
109}
110
111impl AgentUpdate {
112 /// Returns the account name as [`CStr`].
113 #[inline]
114 pub fn account_c(&self) -> &CStr {
115 unsafe { CStr::from_ptr(self.account.as_ptr()) }
116 }
117
118 /// Returns the account name as [`str`].
119 #[inline]
120 pub fn account(&self) -> Option<&str> {
121 self.account_c().to_str().ok()
122 }
123
124 /// Returns the character name as [`Cstr`].
125 #[inline]
126 pub fn character_c(&self) -> &CStr {
127 unsafe { CStr::from_ptr(self.character.as_ptr()) }
128 }
129
130 /// Returns the character name as [`str`].
131 #[inline]
132 pub fn character(&self) -> Option<&str> {
133 self.character_c().to_str().ok()
134 }
135
136 /// Whether the agent has been added or removed.
137 #[inline]
138 pub fn is_added(&self) -> bool {
139 self.added != 0
140 }
141
142 /// Whether the agent is the new target.
143 #[inline]
144 pub fn is_target(&self) -> bool {
145 self.target != 0
146 }
147
148 /// Whether the agent is self.
149 #[inline]
150 pub fn is_self(&self) -> bool {
151 self.is_self != 0
152 }
153}
154
155/// ArcDPS EVTC combat event data.
156#[derive(Debug)]
157#[repr(C)]
158pub struct CombatData {
159 event: *const evtc::Event,
160 src: *const Agent,
161 dst: *const Agent,
162 skill_name: *const c_char,
163 pub id: u64,
164 pub rev: u64,
165}
166
167impl CombatData {
168 /// Returns the combat data as tuple.
169 #[inline]
170 pub fn as_tuple(
171 &self,
172 ) -> (
173 Option<&evtc::Event>,
174 Option<&Agent>,
175 Option<&Agent>,
176 u64,
177 u64,
178 ) {
179 (self.event(), self.src(), self.dst(), self.id, self.rev)
180 }
181
182 /// Returns a pointer to the [`Event`].
183 #[inline]
184 pub fn event_ptr(&self) -> *const evtc::Event {
185 self.event
186 }
187
188 /// Returns the [`Event`](evtc::Event).
189 #[inline]
190 pub fn event(&self) -> Option<&evtc::Event> {
191 unsafe { self.event.as_ref() }
192 }
193
194 /// Returns a pointer to the source [`Agent`].
195 #[inline]
196 pub fn src_ptr(&self) -> *const Agent {
197 self.src
198 }
199
200 /// Returns the source [`Agent`].
201 #[inline]
202 pub fn src(&self) -> Option<&Agent> {
203 unsafe { self.src.as_ref() }
204 }
205
206 /// Returns a pointer to the destination [`Agent`].
207 #[inline]
208 pub fn dst_ptr(&self) -> *const Agent {
209 self.dst
210 }
211
212 /// Returns the destination [`Agent`].
213 #[inline]
214 pub fn dst(&self) -> Option<&Agent> {
215 unsafe { self.dst.as_ref() }
216 }
217
218 /// Returns the skill name as [`CStr`].
219 #[inline]
220 pub fn skill_name_c(&self) -> Option<&CStr> {
221 (!self.skill_name.is_null()).then(|| unsafe { CStr::from_ptr(self.skill_name) })
222 }
223
224 /// Returns the skill name as [`str`].
225 #[inline]
226 pub fn skill_name(&self) -> Option<&str> {
227 self.skill_name_c()?.to_str().ok()
228 }
229}